package com.imooc.coupon.executor;

import com.alibaba.fastjson.JSON;
import com.imooc.coupon.support.vo.SettlementInfo;
import lombok.extern.slf4j.Slf4j;

/**
 * 单个优惠券使用规则结算执行器公共代码抽取
 *
 * Created By TINY
 * Create Time 2020/2/12
 **/
@Slf4j
public abstract class AbstractRuleExecutor extends AbstractExecutor {

    /**
     * 按优惠券规则进行结算，如果用户传入的结算信息对象 {@link SettlementInfo}
     * 不合法，返回一个无效的 {@link SettlementInfo}
     *
     * @param settlementInfo {@link SettlementInfo} 结算信息对象
     * @return {@link SettlementInfo} 按规则计算后的结算信息对象
     */
    @Override
    public SettlementInfo computeRule(SettlementInfo settlementInfo) {

        // 商品的原始总价（保留两位小数）
        double goodsOriginalCost = retain2Decimals(computeAllGoodsCost(
                settlementInfo.getGoodsInfos()
        ));
        SettlementInfo probability = processGoodsTypeNotSupport(
                settlementInfo, goodsOriginalCost
        );

        if (null != probability) { // 优惠券不支持商品类型
            log.warn("({}) 优惠券不支持此商品类型：{}",
                    supports().getDescription(), JSON.toJSONString(
                            settlementInfo.getGoodsInfos()
            ));
            return probability;
        }

        settlementInfo.setCost(goodsOriginalCost); // 设置商品原始总价
        settlementInfo = cProcess(settlementInfo); // 核心规则计算逻辑

        log.info("使用了({})优惠券，商品原始总价：{}，商品折扣总价：{}",
                supports().getDescription(),
                goodsOriginalCost, settlementInfo.getCost());

        return settlementInfo;
    }

    /**
     * 核心的优惠券规则计算逻辑实现，由具体子类去填写
     *
     * @param settlementInfo {@link SettlementInfo} 结算信息对象
     * @return {@link SettlementInfo} 由子类结算处理后的结算信息对象
     */
    protected abstract SettlementInfo cProcess(SettlementInfo settlementInfo);
}
